#include<string>
#include<vector>
#include<queue>
#include<unordered_map>
#include<mutex>
#include<unistd.h>
#include "../buttonrpc/buttonrpc.hpp"
#include "utils.hpp"

using std::mutex;
using std::vector;
using std::string;
using std::queue;

// 超时检测的时间戳
struct TimeStamp{
    time_t time;  
    bool fin; // true 正常完成
};

class Coordinator{

public:
    Coordinator(vector<string> files, int nReduce);
    TaskResponse AssignTask();                                    // 分配任务
    void*        TaskFin(int argsID);                             // 任务完成
    bool         TimeTick();                                      // 处理超时重发
    int          lenTaskFin(unordered_map<int, TimeStamp> &map);  // 获取正常完成任务的数量
    bool         Done();                                          // 任务全部完成
    ~Coordinator();

private:
    vector<string>    files;                       // 所有需要处理的文件——map的工作数量
    int               state;                       // 0 map 1 reduce 2 fin 标识位
    int               NumMapTask;                  // map任务数量
    int               NumReduceTask;               // reduce任务数量
    mutex             c_lock;                      // 互斥锁，保护共享数据
    queue<Task>       MapTasks;                    // 待处理的map工作队列
    queue<Task>       ReduceTasks;                 // 待处理的reduce工作队列
    unordered_map<int, TimeStamp> MapTaskFins;     // 处理完的map
    unordered_map<int, TimeStamp> ReduceTaskFins;  // 处理完的reduce

};

Coordinator::Coordinator(vector<string> files, int nReduce) : state(0), 
                                                              NumMapTask(files.size()),
                                                              NumReduceTask(nReduce),
                                                              files(files)
{
    time_t time_now = time(nullptr);
    // 分配map任务
    for (int i = 0; i < files.size(); i++)
    {
        this->MapTasks.emplace(Task(files[i], i));
        this->MapTaskFins.insert(make_pair(i, TimeStamp{time_now, false}));
    }
}

bool Coordinator::Done(){
    if (!TimeTick())  return false;  // 若触发超时重发，则代表没有完成全部任务

    bool ret = false;
    if (lenTaskFin(this->ReduceTaskFins) == this->NumReduceTask){ // 统计完成的reduce任务
        ret = true;
        lock_guard<mutex> lock(c_lock);
        this->state = 2;
    }
    return ret;
}

int Coordinator::lenTaskFin(unordered_map<int, TimeStamp> &map){
    int len = 0;
    for (auto &&m : map){
        if (m.second.fin) len++;
    }
    return len;
}
